package com.incross.dawin.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import org.apache.http.HttpResponse;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;

import com.incross.dawin.http.BKConnectionManager;

public class BKErrorHandler implements BKConnectionManager.RequestStateListener {
	private static final String BK_ERROR_HANDLER_KEY = "bk_error_handler_key";
	private static final String PREF_ERROR = "error_preferences_key";
	
	private static final int REQUEST_RETRY_SEND_TAG = 10000;
	private static final int REQUEST_ERROR_TAG = 10001;
	
	public static final int WRITE_ON_FILE = 100;
	public static final int WRITE_ON_PREFERENCES = 200;
	
	private static final String FOLDER_NAME = "/incross/failedList/";
	private static final String FILE_NAME = "failedlist.txt";
	
	private Context mContext;
	private SharedPreferences mPrefs;
	
	private File mSaveFile;
	
	private String mPath;
	
	private int mSaveMode = WRITE_ON_FILE; // file write default.
	
	private ArrayList<String> mFailedList;
	
	private BKConnectionManager mConnectionManager;
	private int mRetryCount = 0;
	
	public BKErrorHandler(Context context) {
		mContext = context;
		init();
	}
	
	public BKErrorHandler(Context context, int saveMode) {
		mSaveMode = saveMode;
		mContext = context;
		init();
	}
	
	
	private void init() {
		// preference init
		mPrefs = mContext.getSharedPreferences(BK_ERROR_HANDLER_KEY, Context.MODE_PRIVATE);
		
		mConnectionManager = new BKConnectionManager(mContext);
		mConnectionManager.setOnConnectionStateListener(this);
		
		// preparing for write to sd card
		mPath = Environment.getExternalStorageDirectory().getAbsolutePath();
		mPath += FOLDER_NAME;
		File directory = new File(mPath);
		if(!directory.isDirectory()) {
			directory.mkdirs();
			BKLog.i("directory not exists. make directory.");
		}
		mPath += FILE_NAME;
		mSaveFile = new File(mPath);
		
		mFailedList = getFailedWorks();
		
		
		/*************************** test codes below ************************************/
		
		/*JSONArray arr = new JSONArray();
		JSONObject obj = new JSONObject();
		
		try {
			arr.put(0, "http://112.169.59.43/play_tq?gcd=010510&mcd=0204010&pcd=0180105&scd=0301010&ccd=01201011&uid=MjQ2OWU2NmQtN2MzMC00Y2JmLTg5YTItYWZmYjQ3MGEwOTMz");
			arr.put(1, "http://112.169.59.43/play_mp?gcd=010510&mcd=0204010&pcd=0180105&scd=0301010&ccd=01201011&uid=MjQ2OWU2NmQtN2MzMC00Y2JmLTg5YTItYWZmYjQ3MGEwOTMz");
			arr.put(2, "http://112.169.59.43/play_complete?gcd=010510&mcd=0204010&pcd=0180105&scd=0301010&ccd=01201011&uid=MjQ2OWU2NmQtN2MzMC00Y2JmLTg5YTItYWZmYjQ3MGEwOTMz");
			arr.length();
			
			obj.put("list", arr);
			
			BKLog.e"obj : " + obj.toString());
			BKLog.e"length : " + arr.length());
			
			saveToFile(obj.toString());
		} catch (JSONException e) {
			e.printStackTrace();
		}*/
		
	}
	
	public void setSaveMode(int mode) {
		mSaveMode = mode;
	}
	
	
	
	public boolean isFailedWorkAvailable() { 
		boolean isAvailable = false;
		
		if(mFailedList.size() != 0) {
			isAvailable = true;
		}
		
		return isAvailable;
	}
	
	public boolean saveFailedWork(String failedUrl) {
		boolean isSuccess = false;
		
		if(failedUrl != null) {
			mFailedList.add(failedUrl);
		}
		
		JSONObject saveContent = new JSONObject();
		
		try {
			JSONArray arr = new JSONArray();
			
			for(int i = 0; i < mFailedList.size(); i++) {
				arr.put(i, mFailedList.get(i));
			}
			
			saveContent.put("list", arr);
			
			if(mSaveMode == WRITE_ON_FILE) {
				isSuccess = saveToFile(saveContent.toString());
			} else if(mSaveMode == WRITE_ON_PREFERENCES) {
				saveToPreferences(saveContent.toString());
				isSuccess = true;
			} else {
				isSuccess = false;
			}
			
		} catch(JSONException e) {
			e.printStackTrace();
			isSuccess = false;
		}
		
		
		return isSuccess;
	}
	
	public ArrayList<String> getFailedWorks() {
		ArrayList<String> result = new ArrayList<String>();
		
		if(mSaveMode == WRITE_ON_FILE) {
			result = loadFromFile();
		} else if(mSaveMode == WRITE_ON_PREFERENCES) {
			result = loadFromPreferneces();
		}
		
		return result;
	}
	
	
	/**
	 * remove from failed work list for index.
	 * @param which : removes specified index
	 * @return
	 */
	public boolean removeFailedWork(int which) {
		BKLog.i("remove");
		if(which < 0 || which > mFailedList.size()) {
			return false;
		}
		mFailedList.remove(which);
		
		
		JSONObject saveContent = new JSONObject();
		JSONArray arr= new JSONArray();
		
		try {
			if(mFailedList.size() != 0) {
				for(String str: mFailedList) {
					arr.put(str);
				}
			}
			
			saveContent.put("list", arr);
		} catch(JSONException e) {
			e.printStackTrace();
		}
		
		saveToFile(saveContent.toString());
		/*
		if(arr.length() > 0) {
			
		} else {
			BKLog.e("< 0");
			File saveFile = new File(mPath);
			if(saveFile.isFile() && saveFile.exists()) {
				saveFile.delete();
			}
		}*/
		
		BKLog.i("remove finish");
		return true;
	}
	
	/**
	 * remove from failed work list for string.
	 * @param what : removes specified url
	 * @return
	 */
	public boolean removeFailedWork(String what) {
		if(what == null || what.equals("")) {
			return false;
		}
		
		boolean result = mFailedList.remove(what);
		
		saveToFile(null);
		
		return result;
	}
	
	/**
	 * send failed request if list count is not 0.
	 */
	public int sendFailedRequest() {
		int result = -1;
		if(mRetryCount < 5) {
			if(mFailedList.size() > 0) {
				mConnectionManager.sendRequest(REQUEST_RETRY_SEND_TAG, mFailedList.get(0), null);
				result = 0;
			} else {
				result = 10;
				BKLog.w("No failed list or failed list send finished");
			}
		}
		return result;
	}
	
	
	
	private boolean saveToFile(String content) {
		FileOutputStream fos;
		
		File saveFile = new File(mPath);
		if(saveFile.isFile() && saveFile.exists()) {
			saveFile.delete();
		}
		
		try{
			fos = new FileOutputStream(mSaveFile);
			fos.write(content.toString().getBytes());
			fos.close();
		} catch(IOException e){
			return false;
		}
		
		BKLog.i("saveSuccess");
		return true;
	}
	
	private ArrayList<String> loadFromFile() {
		FileInputStream fis;
		String data = null;
		ArrayList<String> result = new ArrayList<String>();
		
		int size = 0;
		File file = new File(mPath);
		try {
			fis = new FileInputStream(file);
			size = fis.available();
			byte[] buffer = new byte[size];
			fis.read(buffer);
			
			data = new String(buffer);
			
			fis.close();
		} catch(IOException e) {
			BKLog.w("SavedFile not found..");
		}

		if(data != null) {
			try {
				JSONObject obj = new JSONObject(data);
				JSONArray arr = obj.getJSONArray("list");
				
				if(arr.length() != 0) {
					for(int i = 0; i < arr.length(); i++) {
						result.add(arr.getString(i));
					}
				}
				
			} catch(JSONException e) {
				e.printStackTrace();
			}
		}
		
		if(result.size() != 0) {
			for(String str: result) {
				BKLog.i("saved value : " + str);
			}
		}
		
		return result;
	}
	
	private void saveToPreferences(String content) {
		SharedPreferences.Editor editor = mPrefs.edit();
		editor.putString(PREF_ERROR, content);
		editor.commit();
	}
	
	private ArrayList<String> loadFromPreferneces() {
		ArrayList<String> result = new ArrayList<String>();
		
		String content = mPrefs.getString(PREF_ERROR, "");
		
		if(content != null && !content.equals("")) {
			try {
				JSONObject obj = new JSONObject(content);
				JSONArray arr = obj.getJSONArray("list");
				
				if(arr != null && arr.length() != 0) {
					for(int i = 0; i < arr.length(); i++) {
						result.add(arr.getString(i));
					}
				}
				
			} catch(JSONException e) {
				e.printStackTrace();
			}
			
		}
		
		return result;
	}
	
	public void sendErrorTag(String tag) {
		BKConnectionManager connManager = new BKConnectionManager(mContext);
		connManager.setOnConnectionStateListener(this);
		if(tag != null) {
			connManager.sendRequest(REQUEST_ERROR_TAG, tag, null);
			BKLog.e("Send error log : " + tag);
		}
	}
	
	@Override
	public void onRequestFinished(int whichRequest, HttpResponse result,
			String extractString) {
		// delete list if it send success.
		if(whichRequest == REQUEST_RETRY_SEND_TAG) {
			mRetryCount = 0;
			
			BKLog.i("failed list before delete");
			for(String str: mFailedList) {
				BKLog.i(str);
			}
			
			removeFailedWork(0);
			
			BKLog.i("\n--------------------------------------------------------------------------------\n");
			BKLog.i("failed list after delete");
			for(String str: mFailedList) {
				BKLog.i(str);
			}
			
			
			if(mFailedList.size() > 0) {
				BKLog.i("failed list remained : " + mFailedList.size());
				sendFailedRequest();
			} else {
				
			}
			
		} else if(whichRequest == REQUEST_ERROR_TAG) {
			BKLog.d("Error log send success");
		}
		
	}

	@Override
	public void onRequestError(int whichRequest, int errorCode, String message) {
		if(whichRequest == REQUEST_RETRY_SEND_TAG) {
			mRetryCount++;
			if(mRetryCount < 5) {
				BKLog.w("retry..." + mRetryCount);
				sendFailedRequest();
			} else {
				BKLog.e("Finish retry to send failed list.");
			}
		} else if(whichRequest == REQUEST_ERROR_TAG) {
			BKLog.e("Error log send failure");
		}
		
	}
	
}
